home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / tcltk / tk8.4 / xmfbox.tcl < prev   
Text File  |  2009-04-29  |  25KB  |  964 lines

  1. # xmfbox.tcl --
  2. #
  3. #    Implements the "Motif" style file selection dialog for the
  4. #    Unix platform. This implementation is used only if the
  5. #    "::tk_strictMotif" flag is set.
  6. #
  7. # RCS: @(#) $Id: xmfbox.tcl,v 1.25.2.3 2006/03/17 10:50:11 patthoyts Exp $
  8. #
  9. # Copyright (c) 1996 Sun Microsystems, Inc.
  10. # Copyright (c) 1998-2000 Scriptics Corporation
  11. #
  12. # See the file "license.terms" for information on usage and redistribution
  13. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  14.  
  15. namespace eval ::tk::dialog {}
  16. namespace eval ::tk::dialog::file {}
  17.  
  18.  
  19. # ::tk::MotifFDialog --
  20. #
  21. #    Implements a file dialog similar to the standard Motif file
  22. #    selection box.
  23. #
  24. # Arguments:
  25. #    type        "open" or "save"
  26. #    args        Options parsed by the procedure.
  27. #
  28. # Results:
  29. #    When -multiple is set to 0, this returns the absolute pathname
  30. #    of the selected file. (NOTE: This is not the same as a single
  31. #    element list.)
  32. #    When -multiple is set to > 0, this returns a Tcl list of absolute
  33. #       pathnames. The argument for -multiple is ignored, but for consistency
  34. #       with Windows it defines the maximum amount of memory to allocate for
  35. #       the returned filenames.
  36.  
  37. proc ::tk::MotifFDialog {type args} {
  38.     variable ::tk::Priv
  39.     set dataName __tk_filedialog
  40.     upvar ::tk::dialog::file::$dataName data
  41.  
  42.     set w [MotifFDialog_Create $dataName $type $args]
  43.  
  44.     # Set a grab and claim the focus too.
  45.  
  46.     ::tk::SetFocusGrab $w $data(sEnt)
  47.     $data(sEnt) selection range 0 end
  48.  
  49.     # Wait for the user to respond, then restore the focus and
  50.     # return the index of the selected button.  Restore the focus
  51.     # before deleting the window, since otherwise the window manager
  52.     # may take the focus away so we can't redirect it.  Finally,
  53.     # restore any grab that was in effect.
  54.  
  55.     vwait ::tk::Priv(selectFilePath)
  56.     set result $Priv(selectFilePath)
  57.     ::tk::RestoreFocusGrab $w $data(sEnt) withdraw
  58.  
  59.     return $result
  60. }
  61.  
  62. # ::tk::MotifFDialog_Create --
  63. #
  64. #    Creates the Motif file dialog (if it doesn't exist yet) and
  65. #    initialize the internal data structure associated with the
  66. #    dialog.
  67. #
  68. #    This procedure is used by ::tk::MotifFDialog to create the
  69. #    dialog. It's also used by the test suite to test the Motif
  70. #    file dialog implementation. User code shouldn't call this
  71. #    procedure directly.
  72. #
  73. # Arguments:
  74. #    dataName    Name of the global "data" array for the file dialog.
  75. #    type        "Save" or "Open"
  76. #    argList        Options parsed by the procedure.
  77. #
  78. # Results:
  79. #    Pathname of the file dialog.
  80.  
  81. proc ::tk::MotifFDialog_Create {dataName type argList} {
  82.     upvar ::tk::dialog::file::$dataName data
  83.  
  84.     MotifFDialog_Config $dataName $type $argList
  85.  
  86.     if {$data(-parent) eq "."} {
  87.         set w .$dataName
  88.     } else {
  89.         set w $data(-parent).$dataName
  90.     }
  91.  
  92.     # (re)create the dialog box if necessary
  93.     #
  94.     if {![winfo exists $w]} {
  95.     MotifFDialog_BuildUI $w
  96.     } elseif {[winfo class $w] ne "TkMotifFDialog"} {
  97.     destroy $w
  98.     MotifFDialog_BuildUI $w
  99.     } else {
  100.     set data(fEnt) $w.top.f1.ent
  101.     set data(dList) $w.top.f2.a.l
  102.     set data(fList) $w.top.f2.b.l
  103.     set data(sEnt) $w.top.f3.ent
  104.     set data(okBtn) $w.bot.ok
  105.     set data(filterBtn) $w.bot.filter
  106.     set data(cancelBtn) $w.bot.cancel
  107.     }
  108.     MotifFDialog_SetListMode $w
  109.  
  110.     # Dialog boxes should be transient with respect to their parent,
  111.     # so that they will always stay on top of their parent window.  However,
  112.     # some window managers will create the window as withdrawn if the parent
  113.     # window is withdrawn or iconified.  Combined with the grab we put on the
  114.     # window, this can hang the entire application.  Therefore we only make
  115.     # the dialog transient if the parent is viewable.
  116.  
  117.     if {[winfo viewable [winfo toplevel $data(-parent)]] } {
  118.     wm transient $w $data(-parent)
  119.     }
  120.  
  121.     MotifFDialog_FileTypes $w
  122.     MotifFDialog_Update $w
  123.  
  124.     # Withdraw the window, then update all the geometry information
  125.     # so we know how big it wants to be, then center the window in the
  126.     # display (Motif style) and de-iconify it.
  127.  
  128.     ::tk::PlaceWindow $w
  129.     wm title $w $data(-title)
  130.  
  131.     return $w
  132. }
  133.  
  134. # ::tk::MotifFDialog_FileTypes --
  135. #
  136. #    Checks the -filetypes option. If present this adds a list of radio-
  137. #    buttons to pick the file types from.
  138. #
  139. # Arguments:
  140. #    w        Pathname of the tk_get*File dialogue.
  141. #
  142. # Results:
  143. #    none
  144.  
  145. proc ::tk::MotifFDialog_FileTypes {w} {
  146.     upvar ::tk::dialog::file::[winfo name $w] data
  147.  
  148.     set f $w.top.f3.types
  149.     destroy $f
  150.  
  151.     # No file types: use "*" as the filter and display no radio-buttons
  152.     if {$data(-filetypes) eq ""} {
  153.     set data(filter) *
  154.     return
  155.     }
  156.  
  157.     # The filetypes radiobuttons
  158.     # set data(fileType) $data(-defaulttype)
  159.     set data(fileType) 0
  160.  
  161.     MotifFDialog_SetFilter $w [lindex $data(-filetypes) $data(fileType)]
  162.  
  163.     #don't produce radiobuttons for only one filetype
  164.     if {[llength $data(-filetypes)] == 1} {
  165.     return
  166.     }
  167.  
  168.     frame $f
  169.     set cnt 0
  170.     if {$data(-filetypes) ne ""} {
  171.     foreach type $data(-filetypes) {
  172.         set title  [lindex [lindex $type 0] 0]
  173.         set filter [lindex $type 1]
  174.         radiobutton $f.b$cnt \
  175.         -text $title \
  176.         -variable ::tk::dialog::file::[winfo name $w](fileType) \
  177.         -value $cnt \
  178.         -command "[list tk::MotifFDialog_SetFilter $w $type]"
  179.         pack $f.b$cnt -side left
  180.         incr cnt
  181.     }
  182.     }
  183.     $f.b$data(fileType) invoke
  184.  
  185.     pack $f -side bottom -fill both
  186.  
  187.     return
  188. }
  189.  
  190. # This proc gets called whenever data(filter) is set
  191. #
  192. proc ::tk::MotifFDialog_SetFilter {w type} {
  193.     upvar ::tk::dialog::file::[winfo name $w] data
  194.     variable ::tk::Priv
  195.  
  196.     set data(filter) [lindex $type 1]
  197.     set Priv(selectFileType) [lindex [lindex $type 0] 0]
  198.  
  199.     MotifFDialog_Update $w
  200. }
  201.  
  202. # ::tk::MotifFDialog_Config --
  203. #
  204. #    Iterates over the optional arguments to determine the option
  205. #    values for the Motif file dialog; gives default values to
  206. #    unspecified options.
  207. #
  208. # Arguments:
  209. #    dataName    The name of the global variable in which
  210. #            data for the file dialog is stored.
  211. #    type        "Save" or "Open"
  212. #    argList        Options parsed by the procedure.
  213.  
  214. proc ::tk::MotifFDialog_Config {dataName type argList} {
  215.     upvar ::tk::dialog::file::$dataName data
  216.  
  217.     set data(type) $type
  218.  
  219.     # 1: the configuration specs
  220.     #
  221.     set specs {
  222.     {-defaultextension "" "" ""}
  223.     {-filetypes "" "" ""}
  224.     {-initialdir "" "" ""}
  225.     {-initialfile "" "" ""}
  226.     {-parent "" "" "."}
  227.     {-title "" "" ""}
  228.     }
  229.     if { $type eq "open" } {
  230.     lappend specs {-multiple "" "" "0"}
  231.     }
  232.  
  233.     set data(-multiple) 0
  234.     # 2: default values depending on the type of the dialog
  235.     #
  236.     if {![info exists data(selectPath)]} {
  237.     # first time the dialog has been popped up
  238.     set data(selectPath) [pwd]
  239.     set data(selectFile) ""
  240.     }
  241.  
  242.     # 3: parse the arguments
  243.     #
  244.     tclParseConfigSpec ::tk::dialog::file::$dataName $specs "" $argList
  245.  
  246.     if {$data(-title) eq ""} {
  247.     if {$type eq "open"} {
  248.         if {$data(-multiple) != 0} {
  249.         set data(-title) "[mc {Open Multiple Files}]"
  250.         } else {
  251.         set data(-title) [mc "Open"]
  252.         }
  253.     } else {
  254.         set data(-title) [mc "Save As"]
  255.     }
  256.     }
  257.  
  258.     # 4: set the default directory and selection according to the -initial
  259.     #    settings
  260.     #
  261.     if {$data(-initialdir) ne ""} {
  262.     if {[file isdirectory $data(-initialdir)]} {
  263.         set data(selectPath) [lindex [glob $data(-initialdir)] 0]
  264.     } else {
  265.         set data(selectPath) [pwd]
  266.     }
  267.  
  268.     # Convert the initialdir to an absolute path name.
  269.  
  270.     set old [pwd]
  271.     cd $data(selectPath)
  272.     set data(selectPath) [pwd]
  273.     cd $old
  274.     }
  275.     set data(selectFile) $data(-initialfile)
  276.  
  277.     # 5. Parse the -filetypes option. It is not used by the motif
  278.     #    file dialog, but we check for validity of the value to make sure
  279.     #    the application code also runs fine with the TK file dialog.
  280.     #
  281.     set data(-filetypes) [::tk::FDGetFileTypes $data(-filetypes)]
  282.  
  283.     if {![info exists data(filter)]} {
  284.     set data(filter) *
  285.     }
  286.     if {![winfo exists $data(-parent)]} {
  287.     error "bad window path name \"$data(-parent)\""
  288.     }
  289. }
  290.  
  291. # ::tk::MotifFDialog_BuildUI --
  292. #
  293. #    Builds the UI components of the Motif file dialog.
  294. #
  295. # Arguments:
  296. #     w        Pathname of the dialog to build.
  297. #
  298. # Results:
  299. #     None.
  300.  
  301. proc ::tk::MotifFDialog_BuildUI {w} {
  302.     set dataName [lindex [split $w .] end]
  303.     upvar ::tk::dialog::file::$dataName data
  304.  
  305.     # Create the dialog toplevel and internal frames.
  306.     #
  307.     toplevel $w -class TkMotifFDialog
  308.     set top [frame $w.top -relief raised -bd 1]
  309.     set bot [frame $w.bot -relief raised -bd 1]
  310.  
  311.     pack $w.bot -side bottom -fill x
  312.     pack $w.top -side top -expand yes -fill both
  313.  
  314.     set f1 [frame $top.f1]
  315.     set f2 [frame $top.f2]
  316.     set f3 [frame $top.f3]
  317.  
  318.     pack $f1 -side top    -fill x
  319.     pack $f3 -side bottom -fill x
  320.     pack $f2 -expand yes -fill both
  321.  
  322.     set f2a [frame $f2.a]
  323.     set f2b [frame $f2.b]
  324.  
  325.     grid $f2a -row 0 -column 0 -rowspan 1 -columnspan 1 -padx 4 -pady 4 \
  326.     -sticky news
  327.     grid $f2b -row 0 -column 1 -rowspan 1 -columnspan 1 -padx 4 -pady 4 \
  328.     -sticky news
  329.     grid rowconfigure $f2 0    -minsize 0   -weight 1
  330.     grid columnconfigure $f2 0 -minsize 0   -weight 1
  331.     grid columnconfigure $f2 1 -minsize 150 -weight 2
  332.  
  333.     # The Filter box
  334.     #
  335.     bind [::tk::AmpWidget label $f1.lab -text [mc "Fil&ter:"] -anchor w] \
  336.     <<AltUnderlined>> [list focus $f1.ent]
  337.     entry $f1.ent
  338.     pack $f1.lab -side top -fill x -padx 6 -pady 4
  339.     pack $f1.ent -side top -fill x -padx 4 -pady 0
  340.     set data(fEnt) $f1.ent
  341.  
  342.     # The file and directory lists
  343.     #
  344.     set data(dList) [MotifFDialog_MakeSList $w $f2a \
  345.         [mc "&Directory:"] DList]
  346.     set data(fList) [MotifFDialog_MakeSList $w $f2b \
  347.         [mc "Fi&les:"]     FList]
  348.  
  349.     # The Selection box
  350.     #
  351.     bind [::tk::AmpWidget label $f3.lab -text [mc "&Selection:"] -anchor w] \
  352.     <<AltUnderlined>> [list focus $f3.ent]
  353.     entry $f3.ent
  354.     pack $f3.lab -side top -fill x -padx 6 -pady 0
  355.     pack $f3.ent -side top -fill x -padx 4 -pady 4
  356.     set data(sEnt) $f3.ent
  357.  
  358.     # The buttons
  359.     #
  360.     set maxWidth [::tk::mcmaxamp &OK &Filter &Cancel]
  361.     set maxWidth [expr {$maxWidth<6?6:$maxWidth}]
  362.     set data(okBtn) [::tk::AmpWidget button $bot.ok -text [mc "&OK"] \
  363.         -width $maxWidth \
  364.         -command [list tk::MotifFDialog_OkCmd $w]]
  365.     set data(filterBtn) [::tk::AmpWidget button $bot.filter -text [mc "&Filter"] \
  366.         -width $maxWidth \
  367.         -command [list tk::MotifFDialog_FilterCmd $w]]
  368.     set data(cancelBtn) [::tk::AmpWidget button $bot.cancel -text [mc "&Cancel"] \
  369.         -width $maxWidth \
  370.         -command [list tk::MotifFDialog_CancelCmd $w]]
  371.  
  372.     pack $bot.ok $bot.filter $bot.cancel -padx 10 -pady 10 -expand yes \
  373.     -side left
  374.  
  375.     # Create the bindings:
  376.     #
  377.     bind $w <Alt-Key> [list ::tk::AltKeyInDialog $w %A]
  378.  
  379.     bind $data(fEnt) <Return> [list tk::MotifFDialog_ActivateFEnt $w]
  380.     bind $data(sEnt) <Return> [list tk::MotifFDialog_ActivateSEnt $w]
  381.     bind $w <Escape> [list tk::MotifFDialog_CancelCmd $w]
  382.     bind $w.bot <Destroy> {set ::tk::Priv(selectFilePath) {}}
  383.  
  384.     wm protocol $w WM_DELETE_WINDOW [list tk::MotifFDialog_CancelCmd $w]
  385. }
  386.  
  387. proc ::tk::MotifFDialog_SetListMode {w} {
  388.     upvar ::tk::dialog::file::[winfo name $w] data
  389.  
  390.     if {$data(-multiple) != 0} {
  391.     set selectmode extended
  392.     } else {
  393.     set selectmode browse
  394.     }
  395.     set f $w.top.f2.b
  396.     $f.l configure -selectmode $selectmode
  397. }
  398.  
  399. # ::tk::MotifFDialog_MakeSList --
  400. #
  401. #    Create a scrolled-listbox and set the keyboard accelerator
  402. #    bindings so that the list selection follows what the user
  403. #    types.
  404. #
  405. # Arguments:
  406. #    w        Pathname of the dialog box.
  407. #    f        Frame widget inside which to create the scrolled
  408. #            listbox. This frame widget already exists.
  409. #    label        The string to display on top of the listbox.
  410. #    under        Sets the -under option of the label.
  411. #    cmdPrefix    Specifies procedures to call when the listbox is
  412. #            browsed or activated.
  413.  
  414. proc ::tk::MotifFDialog_MakeSList {w f label cmdPrefix} {
  415.     bind [::tk::AmpWidget label $f.lab -text $label -anchor w] \
  416.     <<AltUnderlined>> [list focus $f.l]
  417.     listbox $f.l -width 12 -height 5 -exportselection 0\
  418.     -xscrollcommand [list $f.h set]    -yscrollcommand [list $f.v set]
  419.     scrollbar $f.v -orient vertical   -takefocus 0 -command [list $f.l yview]
  420.     scrollbar $f.h -orient horizontal -takefocus 0 -command [list $f.l xview]
  421.     grid $f.lab -row 0 -column 0 -sticky news -rowspan 1 -columnspan 2 \
  422.     -padx 2 -pady 2
  423.     grid $f.l -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
  424.     grid $f.v -row 1 -column 1 -rowspan 1 -columnspan 1 -sticky news
  425.     grid $f.h -row 2 -column 0 -rowspan 1 -columnspan 1 -sticky news
  426.  
  427.     grid rowconfigure    $f 0 -weight 0 -minsize 0
  428.     grid rowconfigure    $f 1 -weight 1 -minsize 0
  429.     grid columnconfigure $f 0 -weight 1 -minsize 0
  430.  
  431.     # bindings for the listboxes
  432.     #
  433.     set list $f.l
  434.     bind $list <<ListboxSelect>> [list tk::MotifFDialog_Browse$cmdPrefix $w]
  435.     bind $list <Double-ButtonRelease-1> \
  436.         [list tk::MotifFDialog_Activate$cmdPrefix $w]
  437.     bind $list <Return>    "tk::MotifFDialog_Browse$cmdPrefix [list $w]; \
  438.         tk::MotifFDialog_Activate$cmdPrefix [list $w]"
  439.  
  440.     bindtags $list [list Listbox $list [winfo toplevel $list] all]
  441.     ListBoxKeyAccel_Set $list
  442.  
  443.     return $f.l
  444. }
  445.  
  446. # ::tk::MotifFDialog_InterpFilter --
  447. #
  448. #    Interpret the string in the filter entry into two components:
  449. #    the directory and the pattern. If the string is a relative
  450. #    pathname, give a warning to the user and restore the pattern
  451. #    to original.
  452. #
  453. # Arguments:
  454. #    w        pathname of the dialog box.
  455. #
  456. # Results:
  457. #     A list of two elements. The first element is the directory
  458. #     specified # by the filter. The second element is the filter
  459. #     pattern itself.
  460.  
  461. proc ::tk::MotifFDialog_InterpFilter {w} {
  462.     upvar ::tk::dialog::file::[winfo name $w] data
  463.  
  464.     set text [string trim [$data(fEnt) get]]
  465.  
  466.     # Perform tilde substitution
  467.     #
  468.     set badTilde 0
  469.     if {[string index $text 0] eq "~"} {
  470.     set list [file split $text]
  471.     set tilde [lindex $list 0]
  472.     if {[catch {set tilde [glob $tilde]}]} {
  473.         set badTilde 1
  474.     } else {
  475.         set text [eval file join [concat $tilde [lrange $list 1 end]]]
  476.     }
  477.     }
  478.  
  479.     # If the string is a relative pathname, combine it
  480.     # with the current selectPath.
  481.  
  482.     set relative 0
  483.     if {[file pathtype $text] eq "relative"} {
  484.     set relative 1
  485.     } elseif {$badTilde} {
  486.     set relative 1    
  487.     }
  488.  
  489.     if {$relative} {
  490.     tk_messageBox -icon warning -type ok \
  491.         -message "\"$text\" must be an absolute pathname"
  492.  
  493.     $data(fEnt) delete 0 end
  494.     $data(fEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
  495.         $data(filter)]
  496.  
  497.     return [list $data(selectPath) $data(filter)]
  498.     }
  499.  
  500.     set resolved [::tk::dialog::file::JoinFile [file dirname $text] [file tail $text]]
  501.  
  502.     if {[file isdirectory $resolved]} {
  503.     set dir $resolved
  504.     set fil $data(filter)
  505.     } else {
  506.     set dir [file dirname $resolved]
  507.     set fil [file tail    $resolved]
  508.     }
  509.  
  510.     return [list $dir $fil]
  511. }
  512.  
  513. # ::tk::MotifFDialog_Update
  514. #
  515. #    Load the files and synchronize the "filter" and "selection" fields
  516. #    boxes.
  517. #
  518. # Arguments:
  519. #     w         pathname of the dialog box.
  520. #
  521. # Results:
  522. #    None.
  523.  
  524. proc ::tk::MotifFDialog_Update {w} {
  525.     upvar ::tk::dialog::file::[winfo name $w] data
  526.  
  527.     $data(fEnt) delete 0 end
  528.     $data(fEnt) insert 0 \
  529.             [::tk::dialog::file::JoinFile $data(selectPath) $data(filter)]
  530.     $data(sEnt) delete 0 end
  531.     $data(sEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
  532.         $data(selectFile)]
  533.  
  534.     MotifFDialog_LoadFiles $w
  535. }
  536.  
  537. # ::tk::MotifFDialog_LoadFiles --
  538. #
  539. #    Loads the files and directories into the two listboxes according
  540. #    to the filter setting.
  541. #
  542. # Arguments:
  543. #     w         pathname of the dialog box.
  544. #
  545. # Results:
  546. #    None.
  547.  
  548. proc ::tk::MotifFDialog_LoadFiles {w} {
  549.     upvar ::tk::dialog::file::[winfo name $w] data
  550.  
  551.     $data(dList) delete 0 end
  552.     $data(fList) delete 0 end
  553.  
  554.     set appPWD [pwd]
  555.     if {[catch {cd $data(selectPath)}]} {
  556.     cd $appPWD
  557.  
  558.     $data(dList) insert end ".."
  559.     return
  560.     }
  561.  
  562.     # Make the dir and file lists
  563.     #
  564.     # For speed we only have one glob, which reduces the file system
  565.     # calls (good for slow NFS networks).
  566.     #
  567.     # We also do two smaller sorts (files + dirs) instead of one large sort,
  568.     # which gives a small speed increase.
  569.     #
  570.     set top 0
  571.     set dlist ""
  572.     set flist ""
  573.     foreach f [glob -nocomplain .* *] {
  574.     if {[file isdir ./$f]} {
  575.         lappend dlist $f
  576.     } else {
  577.             foreach pat $data(filter) {
  578.                 if {[string match $pat $f]} {
  579.         if {[string match .* $f]} {
  580.             incr top
  581.         }
  582.         lappend flist $f
  583.                     break
  584.         }
  585.             }
  586.     }
  587.     }
  588.     eval [list $data(dList) insert end] [lsort -dictionary $dlist]
  589.     eval [list $data(fList) insert end] [lsort -dictionary $flist]
  590.  
  591.     # The user probably doesn't want to see the . files. We adjust the view
  592.     # so that the listbox displays all the non-dot files
  593.     $data(fList) yview $top
  594.  
  595.     cd $appPWD
  596. }
  597.  
  598. # ::tk::MotifFDialog_BrowseDList --
  599. #
  600. #    This procedure is called when the directory list is browsed
  601. #    (clicked-over) by the user.
  602. #
  603. # Arguments:
  604. #     w        The pathname of the dialog box.
  605. #
  606. # Results:
  607. #    None.    
  608.  
  609. proc ::tk::MotifFDialog_BrowseDList {w} {
  610.     upvar ::tk::dialog::file::[winfo name $w] data
  611.  
  612.     focus $data(dList)
  613.     if {[$data(dList) curselection] eq ""} {
  614.     return
  615.     }
  616.     set subdir [$data(dList) get [$data(dList) curselection]]
  617.     if {$subdir eq ""} {
  618.     return
  619.     }
  620.  
  621.     $data(fList) selection clear 0 end
  622.  
  623.     set list [MotifFDialog_InterpFilter $w]
  624.     set data(filter) [lindex $list 1]
  625.  
  626.     switch -- $subdir {
  627.     . {
  628.         set newSpec [::tk::dialog::file::JoinFile $data(selectPath) $data(filter)]
  629.     }
  630.     .. {
  631.         set newSpec [::tk::dialog::file::JoinFile [file dirname $data(selectPath)] \
  632.         $data(filter)]
  633.     }
  634.     default {
  635.         set newSpec [::tk::dialog::file::JoinFile [::tk::dialog::file::JoinFile \
  636.             $data(selectPath) $subdir] $data(filter)]
  637.     }
  638.     }
  639.  
  640.     $data(fEnt) delete 0 end
  641.     $data(fEnt) insert 0 $newSpec
  642. }
  643.  
  644. # ::tk::MotifFDialog_ActivateDList --
  645. #
  646. #    This procedure is called when the directory list is activated
  647. #    (double-clicked) by the user.
  648. #
  649. # Arguments:
  650. #     w        The pathname of the dialog box.
  651. #
  652. # Results:
  653. #    None.    
  654.  
  655. proc ::tk::MotifFDialog_ActivateDList {w} {
  656.     upvar ::tk::dialog::file::[winfo name $w] data
  657.  
  658.     if {[$data(dList) curselection] eq ""} {
  659.     return
  660.     }
  661.     set subdir [$data(dList) get [$data(dList) curselection]]
  662.     if {$subdir eq ""} {
  663.     return
  664.     }
  665.  
  666.     $data(fList) selection clear 0 end
  667.  
  668.     switch -- $subdir {
  669.     . {
  670.         set newDir $data(selectPath)
  671.     }
  672.     .. {
  673.         set newDir [file dirname $data(selectPath)]
  674.     }
  675.     default {
  676.         set newDir [::tk::dialog::file::JoinFile $data(selectPath) $subdir]
  677.     }
  678.     }
  679.  
  680.     set data(selectPath) $newDir
  681.     MotifFDialog_Update $w
  682.  
  683.     if {$subdir ne ".."} {
  684.     $data(dList) selection set 0
  685.     $data(dList) activate 0
  686.     } else {
  687.     $data(dList) selection set 1
  688.     $data(dList) activate 1
  689.     }
  690. }
  691.  
  692. # ::tk::MotifFDialog_BrowseFList --
  693. #
  694. #    This procedure is called when the file list is browsed
  695. #    (clicked-over) by the user.
  696. #
  697. # Arguments:
  698. #     w        The pathname of the dialog box.
  699. #
  700. # Results:
  701. #    None.    
  702.  
  703. proc ::tk::MotifFDialog_BrowseFList {w} {
  704.     upvar ::tk::dialog::file::[winfo name $w] data
  705.  
  706.     focus $data(fList)
  707.     set data(selectFile) ""
  708.     foreach item [$data(fList) curselection] {
  709.     lappend data(selectFile) [$data(fList) get $item]
  710.     }
  711.     if {[llength $data(selectFile)] == 0} {
  712.     return
  713.     }
  714.  
  715.     $data(dList) selection clear 0 end
  716.  
  717.     $data(fEnt) delete 0 end
  718.     $data(fEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
  719.         $data(filter)]
  720.     $data(fEnt) xview end
  721.  
  722.     # if it's a multiple selection box, just put in the filenames 
  723.     # otherwise put in the full path as usual 
  724.     $data(sEnt) delete 0 end
  725.     if {$data(-multiple) != 0} {
  726.     $data(sEnt) insert 0 $data(selectFile)
  727.     } else {
  728.     $data(sEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
  729.                   [lindex $data(selectFile) 0]]
  730.     }
  731.     $data(sEnt) xview end
  732. }
  733.  
  734. # ::tk::MotifFDialog_ActivateFList --
  735. #
  736. #    This procedure is called when the file list is activated
  737. #    (double-clicked) by the user.
  738. #
  739. # Arguments:
  740. #     w        The pathname of the dialog box.
  741. #
  742. # Results:
  743. #    None.    
  744.  
  745. proc ::tk::MotifFDialog_ActivateFList {w} {
  746.     upvar ::tk::dialog::file::[winfo name $w] data
  747.  
  748.     if {[$data(fList) curselection] eq ""} {
  749.     return
  750.     }
  751.     set data(selectFile) [$data(fList) get [$data(fList) curselection]]
  752.     if {$data(selectFile) eq ""} {
  753.     return
  754.     } else {
  755.     MotifFDialog_ActivateSEnt $w
  756.     }
  757. }
  758.  
  759. # ::tk::MotifFDialog_ActivateFEnt --
  760. #
  761. #    This procedure is called when the user presses Return inside
  762. #    the "filter" entry. It updates the dialog according to the
  763. #    text inside the filter entry.
  764. #
  765. # Arguments:
  766. #     w        The pathname of the dialog box.
  767. #
  768. # Results:
  769. #    None.    
  770.  
  771. proc ::tk::MotifFDialog_ActivateFEnt {w} {
  772.     upvar ::tk::dialog::file::[winfo name $w] data
  773.  
  774.     set list [MotifFDialog_InterpFilter $w]
  775.     set data(selectPath) [lindex $list 0]
  776.     set data(filter)    [lindex $list 1]
  777.  
  778.     MotifFDialog_Update $w
  779. }
  780.  
  781. # ::tk::MotifFDialog_ActivateSEnt --
  782. #
  783. #    This procedure is called when the user presses Return inside
  784. #    the "selection" entry. It sets the ::tk::Priv(selectFilePath) 
  785. #    variable so that the vwait loop in tk::MotifFDialog will be
  786. #    terminated.
  787. #
  788. # Arguments:
  789. #     w        The pathname of the dialog box.
  790. #
  791. # Results:
  792. #    None.    
  793.  
  794. proc ::tk::MotifFDialog_ActivateSEnt {w} {
  795.     variable ::tk::Priv
  796.     upvar ::tk::dialog::file::[winfo name $w] data
  797.  
  798.     set selectFilePath [string trim [$data(sEnt) get]]
  799.  
  800.     if {$selectFilePath eq ""} {
  801.     MotifFDialog_FilterCmd $w
  802.     return
  803.     }
  804.  
  805.     if {$data(-multiple) == 0} {
  806.     set selectFilePath [list $selectFilePath]
  807.     }
  808.  
  809.     if {[file isdirectory [lindex $selectFilePath 0]]} {
  810.     set data(selectPath) [lindex [glob $selectFilePath] 0]
  811.     set data(selectFile) ""
  812.     MotifFDialog_Update $w
  813.     return
  814.     }
  815.  
  816.     set newFileList ""
  817.     foreach item $selectFilePath {
  818.     if {[file pathtype $item] ne "absolute"} {
  819.         set item [file join $data(selectPath) $item]
  820.     } elseif {![file exists [file dirname $item]]} {
  821.         tk_messageBox -icon warning -type ok \
  822.             -message [mc {Directory "%1$s" does not exist.} \
  823.             [file dirname $item]]
  824.         return
  825.     }
  826.  
  827.     if {![file exists $item]} {
  828.         if {$data(type) eq "open"} {
  829.         tk_messageBox -icon warning -type ok \
  830.             -message [mc {File "%1$s" does not exist.} $item]
  831.         return
  832.         }
  833.     } else {
  834.         if {$data(type) eq "save"} {
  835.         set message [format %s%s \
  836.             [mc "File \"%1\$s\" already exists.\n\n" \
  837.             $selectFilePath] \
  838.             [mc {Replace existing file?}]]
  839.         set answer [tk_messageBox -icon warning -type yesno \
  840.             -message $message]
  841.         if {$answer eq "no"} {
  842.             return
  843.         }
  844.         }
  845.     }
  846.     
  847.     lappend newFileList $item
  848.     }
  849.  
  850.     if {$data(-multiple) != 0} {
  851.     set Priv(selectFilePath) $newFileList
  852.     } else {
  853.     set Priv(selectFilePath) [lindex $newFileList 0]
  854.     }
  855.  
  856.     # Set selectFile and selectPath to first item in list
  857.     set Priv(selectFile)     [file tail    [lindex $newFileList 0]]
  858.     set Priv(selectPath)     [file dirname [lindex $newFileList 0]]
  859. }
  860.  
  861.  
  862. proc ::tk::MotifFDialog_OkCmd {w} {
  863.     upvar ::tk::dialog::file::[winfo name $w] data
  864.  
  865.     MotifFDialog_ActivateSEnt $w
  866. }
  867.  
  868. proc ::tk::MotifFDialog_FilterCmd {w} {
  869.     upvar ::tk::dialog::file::[winfo name $w] data
  870.  
  871.     MotifFDialog_ActivateFEnt $w
  872. }
  873.  
  874. proc ::tk::MotifFDialog_CancelCmd {w} {
  875.     variable ::tk::Priv
  876.  
  877.     set Priv(selectFilePath) ""
  878.     set Priv(selectFile)     ""
  879.     set Priv(selectPath)     ""
  880. }
  881.  
  882. proc ::tk::ListBoxKeyAccel_Set {w} {
  883.     bind Listbox <Any-KeyPress> ""
  884.     bind $w <Destroy> [list tk::ListBoxKeyAccel_Unset $w]
  885.     bind $w <Any-KeyPress> [list tk::ListBoxKeyAccel_Key $w %A]
  886. }
  887.  
  888. proc ::tk::ListBoxKeyAccel_Unset {w} {
  889.     variable ::tk::Priv
  890.  
  891.     catch {after cancel $Priv(lbAccel,$w,afterId)}
  892.     unset -nocomplain Priv(lbAccel,$w) Priv(lbAccel,$w,afterId)
  893. }
  894.  
  895. # ::tk::ListBoxKeyAccel_Key--
  896. #
  897. #    This procedure maintains a list of recently entered keystrokes
  898. #    over a listbox widget. It arranges an idle event to move the
  899. #    selection of the listbox to the entry that begins with the
  900. #    keystrokes.
  901. #
  902. # Arguments:
  903. #     w        The pathname of the listbox.
  904. #    key        The key which the user just pressed.
  905. #
  906. # Results:
  907. #    None.    
  908.  
  909. proc ::tk::ListBoxKeyAccel_Key {w key} {
  910.     variable ::tk::Priv
  911.  
  912.     if { $key eq "" } {
  913.     return
  914.     }
  915.     append Priv(lbAccel,$w) $key
  916.     ListBoxKeyAccel_Goto $w $Priv(lbAccel,$w)
  917.     catch {
  918.     after cancel $Priv(lbAccel,$w,afterId)
  919.     }
  920.     set Priv(lbAccel,$w,afterId) [after 500 \
  921.         [list tk::ListBoxKeyAccel_Reset $w]]
  922. }
  923.  
  924. proc ::tk::ListBoxKeyAccel_Goto {w string} {
  925.     variable ::tk::Priv
  926.  
  927.     set string [string tolower $string]
  928.     set end [$w index end]
  929.     set theIndex -1
  930.  
  931.     for {set i 0} {$i < $end} {incr i} {
  932.     set item [string tolower [$w get $i]]
  933.     if {[string compare $string $item] >= 0} {
  934.         set theIndex $i
  935.     }
  936.     if {[string compare $string $item] <= 0} {
  937.         set theIndex $i
  938.         break
  939.     }
  940.     }
  941.  
  942.     if {$theIndex >= 0} {
  943.     $w selection clear 0 end
  944.     $w selection set $theIndex $theIndex
  945.     $w activate $theIndex
  946.     $w see $theIndex
  947.     event generate $w <<ListboxSelect>>
  948.     }
  949. }
  950.  
  951. proc ::tk::ListBoxKeyAccel_Reset {w} {
  952.     variable ::tk::Priv
  953.  
  954.     unset -nocomplain Priv(lbAccel,$w)
  955. }
  956.  
  957. proc ::tk_getFileType {} {
  958.     variable ::tk::Priv
  959.  
  960.     return $Priv(selectFileType)
  961. }
  962.  
  963.